package com.spiro.test.mr;

import sun.net.www.ParseUtil;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Author: Shaoping Huang
 * @Description:
 * @Date: 1/5/2018
 */
public class ClassPathUtils {

    public static String getClassPathWithDotSep(String classPath) {
        File[] files = getClassPath(classPath);
        StringBuilder sb = new StringBuilder();
        boolean isFirst = true;
        for (File file : files) {
            if (isFirst) {
                isFirst = false;
            } else {
                sb.append(",");
            }

            sb.append(file.getAbsolutePath());
        }

        return sb.toString();
    }

    public static URL[] getClassPathURLs(String classPath) {
        File[] classpathFiles = classPath == null ? new File[0] : getClassPath(classPath);
        URL[] classpathUrls = classPath == null ? new URL[0] : pathToURLs(classpathFiles);
        return classpathUrls;
    }

    public static File[] getClassPath(String classPath) {

        String[] classPathItems = getClassPathItems(classPath);
        Set<File> files = new HashSet<>();

        for (String classPathItem : classPathItems) {
            List<File> matchedFiles = getMatchedFiles(classPathItem);
            files.addAll(matchedFiles);
        }

        return files.toArray(new File[0]);
    }

    private static List<File> getMatchedFiles(String classPathItem) {
        List<File> files = new ArrayList<>();
        if (classPathItem.endsWith("*") || classPathItem.endsWith("*.jar")) {
            // end with * or *.jar

            String separator = null;
            if (classPathItem.contains("/")) {
                separator = "/";
            } else {
                separator = "\\";
            }

            int i = classPathItem.lastIndexOf(separator);
            if (i != -1) {
                String parentDir = classPathItem.substring(0, i);

                File file = new File(parentDir);
                if (file.exists() && file.isDirectory()) {

                    FileFilter filter = new FileFilter() {
                        @Override
                        public boolean accept(File pathname) {
                            if (pathname.getName().endsWith(".jar") && pathname.isFile()) {
                                return true;
                            }
                            return false;
                        }
                    };

                    File[] matchedFiles = file.listFiles(filter);
                    for (File matchedFile : matchedFiles) {
                        files.add(matchedFile);
                    }
                }
            }
        } else {
            // not end with * or *.jar
            File file = new File(classPathItem);
            if (file.exists()) {
                files.add(file);
            }
        }
        return files;
    }

    private static String[] getClassPathItems(String classPath) {
        if (classPath != null) {
            return classPath.split(File.pathSeparator);
        }
        return new String[0];
    }

    private static URL[] pathToURLs(File[] files) {
        URL[] urls = new URL[files.length];

        for(int i = 0; i < files.length; ++i) {
            urls[i] = getFileURL(files[i]);
        }

        return urls;
    }

    private static URL getFileURL(File file) {
        try {
            file = file.getCanonicalFile();
        } catch (IOException var3) {
        }

        try {
            return ParseUtil.fileToEncodedURL(file);
        } catch (MalformedURLException var2) {
            throw new InternalError();
        }
    }


    private static String[] _systemClasses =
            {
                    "com.oracle.",
                    "com.sun.",
                    "java.",
                    "javax.",
                    "org.xml.sax.",
                    "org.w3c.dom.",
                    "org.ietf.jgss.",
                    "org.jcp.xml.dsig.internal.",
                    "org.omg.",
                    "sun.",
                    "sunw."
            };

    public static boolean isSystemClass(String name) {
        for (String systemClass : _systemClasses) {
            if (name.startsWith(systemClass)) {
                return true;
            }
        }
        return false;
    }
}
